package cease.util;

import java.util.LinkedList;
import java.util.List;

/**
 * @author dhf
 */
public class CmdLineArgsParser {
    private static enum ArgsParseState {
        NORMAL, ESCAPE, QUOTE, BREAKPOINT
    }

    public static String[] parse(String line) {
        if (null == line) {
            return new String[] {};
        }
        List<String> args = new LinkedList<String>();
        StringBuilder sb = new StringBuilder();
        ArgsParseState state = ArgsParseState.NORMAL;
        for (int i = 0; i < line.length(); i++) {
            char c = line.charAt(i);
            if (state == ArgsParseState.BREAKPOINT) {
                if (c == ' ' || c == '\t') {
                    continue;
                }
                sb = new StringBuilder();
                state = ArgsParseState.NORMAL;
            }
            if (state == ArgsParseState.QUOTE) {
                if (c == '"') {
                    state = ArgsParseState.NORMAL;
                    continue;
                } else if (c == '\\') {
                    state = ArgsParseState.ESCAPE;
                    sb.append(c);
                    continue;
                } else {
                    sb.append(c);
                    continue;
                }
            }
            if (state == ArgsParseState.ESCAPE) {
                if (c == '\\' || c == '"') {
                    sb.deleteCharAt(sb.length() - 1);
                }
                sb.append(c);
                state = ArgsParseState.NORMAL;
                continue;
            }

            switch (c) {
                case '"':
                    state = ArgsParseState.QUOTE;
                    continue;
                case ' ':
                    state = ArgsParseState.BREAKPOINT;
                    if (sb.length() > 0) {
                        args.add(sb.toString());
                        sb = new StringBuilder();
                    }
                    continue;
                default:
                    sb.append(c);
            }
        }
        if (sb.length() > 0) {
            args.add(sb.toString());
        }

        return args.toArray(new String[] {});
    }
}
